package org.lcx.pipeline.impl;

import org.lcx.pipeline.Processor;
import org.lcx.pipeline.bean.PipelineExeption;
import org.lcx.pipeline.bean.PipelineResult;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.text.MessageFormat;

/**
 * pipeline chain<br>
 * 存放chain的所有的pipeline link，同时并执行pipeline chain<br>
 * 是执行过程中的核心类,控制整个chain的事务,默认为:REQUIRED
 */
public class PipelineChain {
	public final Log log = LogFactory.getLog(this.getClass());

	// chain id
	public String id;
	// chain 事务的定义
	public String transaction;
	// chain name
	public String name;
	// chain的第一个processor name
	public String headLink;
	// 存放整个chain的所有pipeline link,key 为 pipelineLink的name值
	public ManagedMap<String, PipelineLink> pipelineLinks;
	// 事务对象
	public PlatformTransactionManager transactionManager;

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getTransaction() {
		return transaction;
	}

	public void setTransaction(String transaction) {
		this.transaction = transaction;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getHeadLink() {
		return headLink;
	}

	public void setHeadLink(String headLink) {
		this.headLink = headLink;
	}

	public ManagedMap<String, PipelineLink> getPipelineLinks() {
		return pipelineLinks;
	}

	public void setPipelineLinks(ManagedMap<String, PipelineLink> pipelineLinks) {
		this.pipelineLinks = pipelineLinks;
	}

	public PlatformTransactionManager getTransactionManager() {
		return transactionManager;
	}

	public void setTransactionManager(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}

	/**
	 * 执行chain
	 * 
	 * @param result
	 * @param pParam
	 * @return
	 */
	public boolean runProcess(PipelineResult result, Object pParam) throws PipelineExeption {
		String nextLinkName = this.headLink;
		PipelineLink link = this.pipelineLinks.get(nextLinkName);
		int ret = 0;

		// 事务处理
		DefaultTransactionDefinition definition = new DefaultTransactionDefinition(PipelineConfig.getTransactionMode(this.transaction));
		TransactionStatus status = transactionManager.getTransaction(definition);
		boolean rollback = true;
		String msgFormat = "pipelineChain(name:{0})初始化事务,事务模型为{1}";
		log.debug(MessageFormat.format(msgFormat, this.name, this.transaction));
		try {
			while (true) {
				if (null == link) {
					msgFormat = "pipelineChain(name:{0}),根据{1}找不到pipelinelink.";
					throw new PipelineExeption(MessageFormat.format(msgFormat, this.name, nextLinkName));
				}
				// 执行代码处理
				ret = link.runProcess(result, pParam);
				if (ret == Processor.STOP_CHAIN_EXECUTION_AND_ROLLBACK) {
					msgFormat = "pipelineChain(name:{0})执行到pipelineLink(name:{1})时终止chain执行,并回滚事务,";
					log.debug(MessageFormat.format(msgFormat, this.name, link.getName()));
					rollback = true;
					break;
				} else if (ret == Processor.STOP_CHAIN_EXECUTION_AND_COMMIT) {
					msgFormat = "pipelineChain(name:{0})执行到pipelineLink(name:{1})时终止chain执行,并提交事务,";
					log.debug(MessageFormat.format(msgFormat, this.name, link.getName()));
					rollback = false;
					break;
				}
				// 是否是pipelineChain最后一步
				if (link.getNextLinkCount() == 0) {
					msgFormat = "pipelineChain(name:{0})执行完成,并提交事务,";
					log.debug(MessageFormat.format(msgFormat, this.name));
					rollback = false;
					break;
				} else {
					// 获取下一个processor
					nextLinkName = link.getNextLink(ret);
					if(null == nextLinkName){
						msgFormat = "pipelineChain(name:{0}), 在link(name:{1})中根据returnValue={2}找不到pipelinelink.";
						throw new PipelineExeption(MessageFormat.format(msgFormat, this.name, link.getName(), ret));
					}
					link = this.pipelineLinks.get(nextLinkName);
				}
			}
		} catch (PipelineExeption e) {
			rollback = true;
			msgFormat = "pipelineChain(name:{0})处理错误";
			log.error(MessageFormat.format(msgFormat, this.name), e);
			throw e;
		} catch (Exception e) {
			rollback = true;
			msgFormat = "pipelineChain(name:{0})处理错误";
			log.error(MessageFormat.format(msgFormat, this.name), e);
			throw new PipelineExeption(e);
		} finally {
			if (rollback) {
				this.transactionManager.rollback(status);
			} else {
				this.transactionManager.commit(status);
			}
		}

		return rollback;
	}

	@Override
	public String toString() {
		return "PipelineChainBean{" + "id='" + id + '\'' + ", transaction='" + transaction + '\'' + ", name='" + name
				+ '\'' + ", headLink='" + headLink + '\'' + ", pipelineLinks=" + pipelineLinks + '}';
	}

}
